package me.zhengjie.utils;


import me.zhengjie.enums.BlockChainEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public abstract class EthUtils {

    /**
     * 获取 Web3j 区块链接
     * @param blockChain
     * @return
     */
    public static Web3j getWeb3jService(BlockChainEnum blockChain) {
        return Web3j.build(new HttpService(blockChain.getRpcUrl()));
    }

    /**
     * 解析Transaction中的Input，提取出收款地址与转账金额
     * 或者叫decode transaction data
     *
     * @param input
     * @return
     */
    public static EthInputData parserTransactionInput(String input) {
        String data = input.substring(0, 9) + input.substring(17);

        Function function = new Function(
                "transfer",
                Arrays.asList(),
                Arrays.asList(
                        new TypeReference<Address>() {
                        },
                        new TypeReference<Uint256>() {
                        }
                )
        );

        List<Type> params = FunctionReturnDecoder.decode(data, function.getOutputParameters());

        String toAddress = params.get(0).getValue().toString();
        String amount = params.get(1).getValue().toString();

        return new EthInputData(toAddress, new BigDecimal(amount));
    }

    /**
     * 构建data
     *
     * @param methodName
     * @param inputParameters
     * @param outputParameters
     * @return
     */
    public static String builderData(String methodName, List<Type> inputParameters, List<TypeReference<?>> outputParameters) {
        if (inputParameters == null) {
            inputParameters = new ArrayList<>(0);
        }

        if (outputParameters == null) {
            outputParameters = new ArrayList<>(0);
        }

        Function function = new Function(methodName, inputParameters, outputParameters);

        return FunctionEncoder.encode(function);
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class EthInputData {
        private String address;
        private BigDecimal amount;
    }
}
